﻿using SuperSocket.Client;
using SuperSocket.ProtoBase;
using System.Buffers;
using System.Net;
using System.Text;
using System.Text.Unicode;

namespace BasicClient
{
    /// <summary>
    /// 我的包
    /// </summary>
    class MyPackageDecode : IPackageDecoder<MyPackage>
    {
        public MyPackage Decode(ref ReadOnlySequence<byte> buffer, object? context)
        {
            var package = new MyPackage();

            var reader = new SequenceReader<byte>(buffer);

            reader.TryRead(out byte opCodeByte);
            package.Code = (OpCode)opCodeByte;

            // skip the two bytes for length, we don't need length any more
            // because we already get the full data of the package in the buffer
            reader.Advance(2);

            reader.TryReadBigEndian(out short sequence);
            package.Sequence = sequence;
            // get the rest of the data in the reader and then read it as utf8 string
            package.Body = string.Empty;

            return package;
        }
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            EasyClient<MyPackage> client0 = new EasyClient<MyPackage>(new MyPackageFilter(new MyPackageDecode()));

            //client0.LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);
            //client0.AsUdp(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1024));

            var client = client0.AsClient();

            if (!await client.ConnectAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3333)))
            {
                Console.WriteLine("Failed to connect the target server.");
                return;
            }

#pragma warning disable CS4014 // 由于此调用不会等待，因此在调用完成前将继续执行当前方法
            Task.Run(async () =>
            {
                while (true)
                {
                    var p = await client.ReceiveAsync();

                    if (p == null) // connection dropped
                        break;

                    Console.WriteLine(p.Body);
                }
            });
#pragma warning restore CS4014 // 由于此调用不会等待，因此在调用完成前将继续执行当前方法

            var txt = System.Text.Encoding.UTF8.GetBytes("Hello World\r\n");

#pragma warning disable CS4014 // 由于此调用不会等待，因此在调用完成前将继续执行当前方法
            Task.Run(async () =>
            {
                while(true)
                {
                    client.SendAsync(new ReadOnlyMemory<byte>(txt));
                    await Task.Delay(2000);
                    //client.SendAsync(new MyPackage());
                }; 
            });
#pragma warning restore CS4014 // 由于此调用不会等待，因此在调用完成前将继续执行当前方法

            Console.WriteLine("Enter any key to exit...");
            Console.ReadKey();
        }
    }
}